package wangwenjun.phase2.concurrencypattern.future;

import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author ChangLiang
 * @date 2020/6/15
 */
@Slf4j
public class FutureService<IN,OUT> implements FutureServiceFactory<IN,OUT> {


    /*FutureService的主要作用在于当提交任务时创建一个新的线程来受理该任务， 进而达到任务异步执
            行的效果*/

    private final static String FUTURE_THREAD_PREFIX = "FUTURE-";

    private final AtomicInteger nextCounter = new AtomicInteger(0);

    private String getThreadName() {
        return FUTURE_THREAD_PREFIX + nextCounter.getAndIncrement();
    }

    @Override
    public Future<?> submit(Runnable runnable) {
        final FutureImpl<Void> future = new FutureImpl<>();
        new Thread(()->{
            runnable.run();
            // 任务执行结束之后将null 作为结果传给future
            future.finish(null);
        },getThreadName()).start();
        return future;
    }

    @Override
    public Future<OUT> submit(Task<IN, OUT> task, IN input, Callback<OUT> callback) {
        final FutureImpl<OUT> future = new FutureImpl<>();
        new Thread(()->{
            log.warn("Thread:{} begin to execute Task#getOutput", Thread.currentThread());
            // 当任务还没完成时，task调用get方法 main线程会被挂起而进入阻塞 注意：这里是main线程，而不是FUTURE-0线程进入阻塞
            OUT result = task.getOutput(input);
            // 任务执行结束之后， 将真实的结果通过finish 方法传递给future
            future.finish(result);
            if (Objects.nonNull(callback)) {
                callback.call(result);
            }
        },getThreadName()).start();
        return future;
    }
}
